//***************************************************************************//
//*
//* 内容摘要：跨平台私有格式文件录制实现
//*	
//* 当前版本：V1.0		
//* 作    者：zhfayuan
//* 完成日期：2019-3-29
//**************************************************************************//
#if !defined(PRIVATE_MUX_H)
#define PRIVATE_MUX_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDCommon.h"
#include "SDLog.h"
#include "SDMutex.h"
#include "CmdProtocolStruct.h"

#define PRIVATE_MUX_VERSION     20190401
#define PRIVATE_MUX_CRC_TEMP    0xABCD1023
//录制私有文件后缀
#define PRIVATE_MUX_FILE_EXTENSION			".me"
//录制私有文件的标志文件后缀
#define PRIVATE_MUX_FLAG_FILE_EXTENSION		".meflag"

//点播时外层播放进度的通知频率(秒)
#define PRIVATE_VOD_NOTIFY_INTERVAL		1

#ifdef WIN32
typedef signed __int64       int64_t;
typedef unsigned __int64     uint64_t;
#endif

typedef struct PRIVATE_FILE_HEAD
{  
	uint64_t unUid;      //设备ID 1
    uint32_t unToken;    //秘钥Token 9
	uint32_t unTimebase;	//选择音频or视频作为基础时钟 13
	uint32_t unStartTime;	//基础时钟的起始时间戳 17
	uint32_t unDuration;    //时长，单位秒
	uint32_t unAudCodec;    //音频编码方式
	uint32_t unVidCodec;    //视频编码方式
	uint32_t unAvPackCC;      //文件包含的数据包数目
	uint32_t unExtraPackCC;      //文件包含的数据包数目
	uint32_t unCRC;         //CRC校验值
	uint32_t unVersion;     //版本号
	uint32_t unReserve[6];	//保留
} PRIVATE_FILE_HEAD;

typedef struct PRIVATE_FILE_ENTRY
{
	uint32_t unAvMsgIndex;
}PRIVATE_FILE_ENTRY;

typedef struct PRIVATE_FILE
{
    struct  PRIVATE_FILE_ENTRY entry;
    struct  PRIVATE_FILE_HEAD head;
}PRIVATE_FILE;

typedef enum
{
	AVPACKET_AUDIO  = 0,
	AVPACKET_VIDEO	= 1,
	AVPACKET_EXTRA_UNDEFINE	= 2,
	AVPACKET_END	= 3, 
	AVPACKET_SYNC   =4,				//点播过程中特定用途
	AVPACKET_GPS    =5				//文件中的GPS位置信息
}E_AVPACKET_TYPE;

//选择音频或视频流作为时钟参考
typedef enum
{
	TIMEBASE_WITH_AUDIO  = 0,
	TIMEBASE_WITH_VIDEO	 = 1,
	TIMEBASE_INVALID 		
}E_PRIVATE_FILE_TIMEBASE;

class CPrivateMux
{
public:
	CPrivateMux();
	virtual ~CPrivateMux();

public:
	//录制文件名[不负责路径创建]、是否生成结束标志文件等信息
    BOOL CreatePrivateMux(const char* pFileName,UINT64 unUid,BYTE byVideoCodec,BYTE byAudioCodec,UINT unToken, BOOL bCreateFlagFile);
	void ClosePrivateMux();
	//输入单个视频AVPacket，1KHZ时基
	BOOL PutVideoPacket(AVPACK* pack, UINT unTotalPacketLen);
	//输入单个音频AVPacket，1KHZ时基
	BOOL PutAudioPacket(AVPACK* pack, UINT unTotalPacketLen);
	//输入单个音频AVPacket，1KHZ时基
	BOOL PutExtraPacket(AVPACK* pack, UINT unTotalPacketLen);
	//获得本次录制目前已写入的字节数MB[不加锁 不绝对精确]
	UINT GetCurrWriteSizeMB();
	//获得本次录制目前已写入的实际媒体时长（秒）[不加锁 不绝对精确]
	UINT GetCurrMediaSeconds();
	//获得本次启动录制至本接口调用的时长(秒)
	UINT GetCurrCreateSeconds();
	UINT GetVideoPackNum();
	UINT GetAudioPackNum();

    //从当前文件指针处读取AVPacket头
    static BOOL ReadPackHead(FILE* pfPackFile, const char* pcFileName, AVPACK_HEAD* ptPackHead);    
    //校验AVPacket头的合法性
    static BOOL IsPackHeadValid(AVPACK_HEAD* ptPackHead);

	//从当前文件指针处读取文件头
	static BOOL ReadFileHead(FILE* pfPackFile, const char* pcFileName, PRIVATE_FILE_HEAD* ptFileHead);
	//校验文件头的合法性
	static BOOL IsFileHeadValid(PRIVATE_FILE_HEAD* ptFileHead);
    //将文件指针偏移到总时长TotalDuration的某个百分比StartPosPercent附近AVPacket，并且保障以视频IDR起始
    static BOOL SkipFileToPos(FILE* pfPackFile, const char* pcFileName, UINT unStartPosPercent,PRIVATE_FILE_HEAD* ptFileHead);
    static BOOL Repair(std::string strName,UINT &duration);
private:
	//录制的私有媒体文件
	FILE *m_pPrivateMediaFile;
	//文件名（带路径）
	char m_acPrivateMediaFileName[1024];
	BOOL m_bCreateFlagFile;
	//写文件互斥锁
	void *m_pvFileWrite;
	//对外接口锁
	void *m_pvVideo;
	void *m_pvAudio;
	void *m_pvExtra;
    time_t m_tLastWriteHead;
	BOOL m_bPrivateMuxClose;
	//是否写入过SPS\PPS，保障从IDR帧开始录制音视频
	BOOL m_bIdrWrited;

	//起始视频时间戳
	UINT m_unVideoStartTs;
	//当前写入视频时间戳
	UINT m_unVideoCurrTs;
	//起始音频时间戳
	UINT m_unAudioStartTs;
	//当前写入音频时间戳
	UINT m_unAudioCurrTs;

    //音视频编码方式
    BYTE    m_byAudioCodec;
    BYTE    m_byVideoCodec;

	//本次写入文件的字节数
	uint64_t m_unFileWriteSize;
    //本次写入文件的包数
    UINT m_nWritePackNum;
    UINT m_nWriteExtraPackNum;
	//本次开始录制到当前的时长（秒）
    UINT m_nWriteVideoPackNum;
    UINT m_nWriteAudioPackNum;
	UINT m_unStartCapTime;
	//时钟参考
	E_PRIVATE_FILE_TIMEBASE m_eTimebase;

private:
	BOOL WritePacketToFile(unsigned char *pBuf, int nLen, BOOL bVideo,BOOL bExtra);

};

#endif
